package com.mezz.bones.im.gateway.handler;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.mezz.bones.im.common.domain.user.ImUserConnectInfo;
import com.mezz.bones.im.common.enums.ActionCodeEnum;
import com.mezz.bones.im.common.result.ImResult;
import com.mezz.bones.im.common.result.ImResultCode;
import com.mezz.bones.im.gateway.manager.UserConnectInfoManager;
import com.mezz.bones.im.gateway.util.ChannelUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.UUID;

/**
 * @author mezz
 * @date 2022-09-23 14:08
 * @description:
 * 检测channel心跳
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {

  @Resource
  private UserConnectInfoManager userConnectInfoManager;

  @Override
  public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

    log.debug("-----------HeartBeatHandler begin-----------");

    if(evt instanceof IdleStateEvent){
      IdleStateEvent event = (IdleStateEvent) evt;

      switch (event.state()) {

        case WRITER_IDLE:
          sendHeartbeat(ctx);
          break;
        case READER_IDLE:
          //强制关闭连接信息
          ImUserConnectInfo userInfo = userConnectInfoManager.getUserConnectInfo(ctx);
          log.info("心跳超时关闭连接----用户[{}]", userInfo == null ? "未登录用户" : userInfo);
          ChannelUtil.sendAndGracefullyClose(ctx.channel(), ImResult.errorMsg(StrUtil.format("心跳超时关闭连接----用户[{}]", userInfo == null ? "未登录用户" : userInfo)));
          break;
      }
    }

    super.userEventTriggered(ctx,evt);

  }

  private void sendHeartbeat(ChannelHandlerContext ctx) {

    ImUserConnectInfo senderUserConnectInfo = userConnectInfoManager.getUserConnectInfo(ctx);

    //消息信息
    Object message = new Date();
    String traceId = UUID.randomUUID().toString();
    String actionCode = ActionCodeEnum.CLIENT_PING_PONG.getCode();
    log.debug("im gateway send actionCode={},client={}, message={}", actionCode, JSONObject.toJSONString(senderUserConnectInfo), JSONObject.toJSONString(message));
    ctx.channel().writeAndFlush(ImResult.data(ImResultCode.SUCCESS,traceId,actionCode,new Date()));

  }

}
